package ncme.auto.framework.core.dynamicDatasource.utils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import ncme.auto.framework.core.exceptions.AutoException;
import ncme.auto.framework.core.exceptions.ExceptionEnum;
import ncme.auto.framework.core.services.Impl.mian.AutoEntityServiceImpl;
import org.apache.ibatis.binding.MapperMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ConvertUtil {

    //service注入需要
    @Autowired
    protected ApplicationContext applicationContext;

    public Object getRealParam(Object originParameter) {
        if (originParameter instanceof MapperMethod.ParamMap) {
            return ((MapperMethod.ParamMap) originParameter).get("param1");
        } else {
            return originParameter;
        }
    }

    /**
     * @param entity 业务实体
     * @return 从业务实体中提取的参数List，除id外
     * @throws IllegalAccessException 字段取值异常
     */
    public List<String> getParamForInsert(Object entity) throws IllegalAccessException {
        List<String> values = new ArrayList<>();
        Field[] declaredFields = entity.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.getName().equals("id")) continue;
            field.setAccessible(true);
            Object value = field.get(entity);
            if (value != null) values.add(value.toString());
        }
        return values;
    }

    public List<String> getParamForUpdate(Object originParameter) throws IllegalAccessException {
        Object entityParam = getRealParam(originParameter);
        List<String> values = getParamForInsert(entityParam);
        try {
            //添加更新条件id
            Field idField = entityParam.getClass().getDeclaredField("id");
            idField.setAccessible(true);
            values.add(idField.get(entityParam).toString());
            //添加更新条件version
            Field versionField = entityParam.getClass().getDeclaredField("version");
            versionField.setAccessible(true);
            if (versionField.get(entityParam) == null) values.add("1");
            else values.add(String.valueOf(Integer.parseInt(versionField.get(entityParam).toString()) - 1));
        } catch (Exception e) {
            throw new AutoException(ExceptionEnum.JDBC, "实体" + entityParam.getClass().getSimpleName() + "缺少id或version字段");
        }
        return values;
    }

    public List<String> getParamForSelect(Object originParameter) {
        List<String> values = new ArrayList<>();
        if (originParameter instanceof MapperMethod.ParamMap) {
            QueryWrapper mapParam = (QueryWrapper) getRealParam(originParameter);
            Map paramMap = mapParam == null ? new HashMap() : mapParam.getParamNameValuePairs();
            Object[] objects = paramMap.values().toArray();
            for (Object object : objects) {
                values.add(object.toString());
            }
        } else {
            values.add(originParameter.toString());
        }
        return values;
    }

    public List<String> getParamForDeleted(Object originParameter) {
        List<String> values = new ArrayList<>();
        values.add(originParameter.toString());
        return values;
    }

    public String setSqlParameters(String originSql, List<String> parameters) {
        //加参数
        StringBuilder execSql = new StringBuilder();
        if (originSql.contains("?")) {
            String[] split = originSql.split("\\?");
            execSql.append(split[0]);
            for (int i = 0; i < split.length - 1; i++) {
                execSql.append("\"");
                execSql.append(parameters.get(i));
                execSql.append("\"");
                execSql.append(split[i + 1]);
            }
        } else execSql.append(originSql);
        return execSql.toString();
    }

    public Object wrapResult(Class<?> entityClass, Object sqlResult) {
        if (entityClass.equals(Integer.class)) return sqlResult;
        if (sqlResult instanceof ArrayList) {
            List<Object> finalResult = new ArrayList<>();
            AutoEntityServiceImpl serviceImpl = (AutoEntityServiceImpl) getServiceImpl(entityClass);
            ArrayList<HashMap<String, Object>> sqlResult1 = (ArrayList<HashMap<String, Object>>) sqlResult;
            for (HashMap<String, Object> rowMap : sqlResult1) {
                Object entityFromMap = serviceImpl.createEntityFromMap(entityClass, rowMap);
                finalResult.add(entityFromMap);
            }
            return finalResult;
        } else return sqlResult;
    }

    private Object getServiceImpl(Class<?> argClass) {
        String entityPath = argClass.getName();
        String simpleName = argClass.getSimpleName();
        String servicePath = entityPath.replace("entity", "service.impl")
                .replace(simpleName, simpleName + "ServiceImpl");
        Class<?> serviceClass = null;
        try {
            serviceClass = Class.forName(servicePath);
        } catch (ClassNotFoundException e) {
            throw new AutoException(ExceptionEnum.NOT_EXIST, servicePath + " not exist");
        }
        Object bean = applicationContext.getBean(serviceClass);
        return bean;
    }

}
